package 
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DTextureFormat;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.display3D.textures.Texture;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.utils.getTimer;
    /**
      *
      * 材质ui动画
    */
    public class uvanimated extends Sprite
    {
    //构造函数中
    public function uvanimated()
      {
       super();
       stage.scaleMode = StageScaleMode.NO_SCALE;
       stage.align = StageAlign.TOP_LEFT;
       stage.frameRate=60;
       var stage3d:Stage3D=this.stage.stage3Ds[0];
       stage3d.addEventListener(Event.CONTEXT3D_CREATE,oncontext3dCreate);//注册创建成功事件。
    stage3d.requestContext3D(); //请求context3d对象   
    }
    //编写context3d创建成功响应函数
    //  
    private function oncontext3dCreate(e:Event):void
      {
       _context3d=e.target.context3D;//得到Context3D对象
    _context3d.configureBackBuffer(800,600,0);//配置缓冲区   
    crateProgram();//创建渲染program
       createMode();//创建模型
    createTexture();//创建材质   
    _context3d.setProgram(_progarm);   //设置对应的渲染程序
    this.addEventListener(Event.ENTER_FRAME,render);//循环渲染
    }
    //创建渲染程序
    private function crateProgram():void
      {
       _progarm=_context3d.createProgram();   
       vetexProgram=new AGALMiniAssembler(true);
       vetexProgram.assemble(Context3DProgramType.VERTEX,
        "m44 op, va0, vc0\n" + // 顶点坐标变换
    "mov vt0, va1 \n" + // save uv in temp register
        "add vt0.xy, vt0.xy, vc4.xy   \n" + // add uv offset  这段就是实现uv动画的关键 （需要注意前面使用了vc0这里必须使用vc4因为一个vc站4个位置）
    "mov v0, vt0  \n" //+ // copy uv
       );

       fragmentProgram=new AGALMiniAssembler(true);
       fragmentProgram.assemble(Context3DProgramType.FRAGMENT,
        "tex ft0, v0, fs0 <2d,repeat,nomip>\n" + //材质贴图
    "mov oc, ft0\n"//输出
    );

       _progarm.upload(vetexProgram.agalcode,fragmentProgram.agalcode);
      }

    /**
       * 创建模型
    */
    private function createMode():void
      {
       var vets:Vector.<Number>=Vector.<Number>([
        // x,y,z                      u,v（vertical）
    0,0.202,0,               0,0,
        0.166,0.202,0,       0.162109375,0,
        0,0,0,                      0,0.197265625,
        0.166,0,0,               0.162109375,0.197265625
       ]);

       _vetexBuffer=_context3d.createVertexBuffer(vets.length/5,5);//创建顶点buffer 这里5表示一个点占五位，前三个是模型坐标后两个是uv坐标 gup是如何知道这样的设定呢？后面的render方法里我会说明
    _vetexBuffer.uploadFromVector(vets,0,vets.length/5);//上传到gpu

       var index:Vector.<uint>=Vector.<uint>([0,1,2,  1,2,3]);//这里是上面顶点的索引顺序
    _indexBuffer=_context3d.createIndexBuffer(index.length);//创建索引buffer
       _indexBuffer.uploadFromVector(index,0,index.length);//上传到gpu
      }
    /**
       * 创建材质
    */
    private function createTexture():void
      {
       _texture=_context3d.createTexture(512,512,Context3DTextureFormat.BGRA,true);//注意，材质的宽和高必须是2的n次方
    var bitmap:Bitmap=new texturedj() as Bitmap;
       var bitmapd:BitmapData=new BitmapData(512,512,true,0);
       bitmapd.draw(bitmap);
       _texture.uploadFromBitmapData(bitmapd); //上传到gpu
      }
      /**
       * 渲染输出
    */
    protected function render(e:Event):void
      {
       _context3d.clear();
       _context3d.setVertexBufferAt(0,_vetexBuffer,0,Context3DVertexBufferFormat.FLOAT_3);//设置vetex前3个为va0 模型坐标xyz
       _context3d.setVertexBufferAt(1,_vetexBuffer,3,Context3DVertexBufferFormat.FLOAT_2);//设置vetex后两个为uv坐标。
    _context3d.setTextureAt(0,this._texture);//设置fs0材质

    var m:Matrix3D = new Matrix3D();
          m.appendScale(2,2,2);//放大两倍
    _context3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,m);//上传vc0 到gpu 为一个Matrix3D
       uvs[0]+=0.162109375;//这里设置x坐标偏移
    uvs[1]=0.197265625*2;//这里设置y坐标偏移
    _context3d.setProgramConstantsFromVector(Context3DProgramType.VERTEX,4,uvs);//上传vc4 常量到gpu，uvs必须为四个
    _context3d.drawTriangles(_indexBuffer);//画三角形
    _context3d.present();//渲染输出
    }
    private var uvs:Vector.<Number>=Vector.<Number>([0.162109375,0.197265625*2,0,0]);//uv坐标偏移依次为(x,y,z,w)

    //成员变量
    private var _context3d:Context3D;
      private var _vetexBuffer:VertexBuffer3D;//缓冲定点
    private var _indexBuffer:IndexBuffer3D;//索引定点
    private var _texture:Texture;//材质
    private var _progarm:Program3D;//

      private var vetexProgram:AGALMiniAssembler;//顶点着色器
    private var fragmentProgram:AGALMiniAssembler;//片段着色器  

    [Embed(source="BlueTownv2_byLunarea.png")]
      public static var texturedj:Class;
  }
}